/*
 * FileSplitterView.java
 */

package org.genalungu.filesplitter;

import java.io.File;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.RandomAccessFile;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileSystemView;
import org.genalungu.filesplitter.io.FileWorker;
import org.genalungu.filesplitter.io.FileWorkerListener;
import org.jdesktop.application.Task;

/**
 * The application's main frame.
 */
public class FileSplitterView extends FrameView {

    private FileWorker fileUtil = new FileWorker();

    public FileSplitterView(SingleFrameApplication app) {
        super(app);

        initComponents();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = FileSplitterApp.getApplication().getMainFrame();
            aboutBox = new FileSplitterAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        FileSplitterApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        mainPanel = new javax.swing.JPanel();
        mainTabbedPane = new javax.swing.JTabbedPane();
        mainSplitPanel = new javax.swing.JPanel();
        splitPanelLeft = new javax.swing.JPanel();
        labelSplitFile = new javax.swing.JLabel();
        labelSplitTargetDir = new javax.swing.JLabel();
        labelSplitParam = new javax.swing.JLabel();
        splitPanelCenter = new javax.swing.JPanel();
        textFieldSplitFile = new javax.swing.JTextField();
        textFieldSplitTargetDir = new javax.swing.JTextField();
        comboSplitParam = new javax.swing.JComboBox();
        splitPanelRight = new javax.swing.JPanel();
        buttonSplitFileBrowse = new javax.swing.JButton();
        buttonBrowseSplitTargetDir = new javax.swing.JButton();
        textFieldSplitParam = new javax.swing.JTextField();
        panelSplitControlButtons = new javax.swing.JPanel();
        buttonSplit = new javax.swing.JButton();
        buttonSplitCancel = new javax.swing.JButton();
        mainMergePanel = new javax.swing.JPanel();
        panelMergeLeft = new javax.swing.JPanel();
        labelMergeFile = new javax.swing.JLabel();
        panelMergeCenter = new javax.swing.JPanel();
        textFieldMergeFile = new javax.swing.JTextField();
        panelMergeRight = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        panelMergeControlButtons = new javax.swing.JPanel();
        buttonPerformMerge = new javax.swing.JButton();
        buttonCancelMerge = new javax.swing.JButton();
        labelExplainMerge = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setLayout(new java.awt.GridLayout(1, 1));

        mainTabbedPane.setName("mainTabbedPane"); // NOI18N

        mainSplitPanel.setName("mainSplitPanel"); // NOI18N
        mainSplitPanel.setLayout(new java.awt.GridBagLayout());

        splitPanelLeft.setName("splitPanelLeft"); // NOI18N
        splitPanelLeft.setLayout(new java.awt.GridLayout(3, 1, 0, 5));

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(org.genalungu.filesplitter.FileSplitterApp.class).getContext().getResourceMap(FileSplitterView.class);
        labelSplitFile.setText(resourceMap.getString("labelSplitFile.text")); // NOI18N
        labelSplitFile.setName("labelSplitFile"); // NOI18N
        splitPanelLeft.add(labelSplitFile);

        labelSplitTargetDir.setText(resourceMap.getString("labelSplitTargetDir.text")); // NOI18N
        labelSplitTargetDir.setName("labelSplitTargetDir"); // NOI18N
        splitPanelLeft.add(labelSplitTargetDir);

        labelSplitParam.setText(resourceMap.getString("labelSplitParam.text")); // NOI18N
        labelSplitParam.setName("labelSplitParam"); // NOI18N
        splitPanelLeft.add(labelSplitParam);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(1, 5, 1, 3);
        mainSplitPanel.add(splitPanelLeft, gridBagConstraints);

        splitPanelCenter.setName("splitPanelCenter"); // NOI18N
        splitPanelCenter.setLayout(new java.awt.GridLayout(3, 1, 0, 5));

        textFieldSplitFile.setText(resourceMap.getString("textFieldSplitFile.text")); // NOI18N
        textFieldSplitFile.setName("textFieldSplitFile"); // NOI18N
        splitPanelCenter.add(textFieldSplitFile);

        textFieldSplitTargetDir.setText(resourceMap.getString("textFieldSplitTargetDir.text")); // NOI18N
        textFieldSplitTargetDir.setName("textFieldSplitTargetDir"); // NOI18N
        splitPanelCenter.add(textFieldSplitTargetDir);

        comboSplitParam.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Split size (Kb)", "Number of files" }));
        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(org.genalungu.filesplitter.FileSplitterApp.class).getContext().getActionMap(FileSplitterView.class, this);
        comboSplitParam.setAction(actionMap.get("onSplitParamSelected")); // NOI18N
        comboSplitParam.setName("comboSplitParam"); // NOI18N
        splitPanelCenter.add(comboSplitParam);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.8;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3);
        mainSplitPanel.add(splitPanelCenter, gridBagConstraints);

        splitPanelRight.setName("splitPanelRight"); // NOI18N
        splitPanelRight.setLayout(new java.awt.GridLayout(3, 1, 0, 5));

        buttonSplitFileBrowse.setAction(actionMap.get("onBrowseSplitFile")); // NOI18N
        buttonSplitFileBrowse.setText(resourceMap.getString("buttonSplitFileBrowse.text")); // NOI18N
        buttonSplitFileBrowse.setName("buttonSplitFileBrowse"); // NOI18N
        splitPanelRight.add(buttonSplitFileBrowse);

        buttonBrowseSplitTargetDir.setAction(actionMap.get("onBrowseSplitTargetDir")); // NOI18N
        buttonBrowseSplitTargetDir.setText(resourceMap.getString("buttonBrowseSplitTargetDir.text")); // NOI18N
        buttonBrowseSplitTargetDir.setName("buttonBrowseSplitTargetDir"); // NOI18N
        splitPanelRight.add(buttonBrowseSplitTargetDir);

        textFieldSplitParam.setText(resourceMap.getString("textFieldSplitParam.text")); // NOI18N
        textFieldSplitParam.setName("textFieldSplitParam"); // NOI18N
        splitPanelRight.add(textFieldSplitParam);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 5);
        mainSplitPanel.add(splitPanelRight, gridBagConstraints);

        panelSplitControlButtons.setName("panelSplitControlButtons"); // NOI18N

        buttonSplit.setAction(actionMap.get("onPerformSplit")); // NOI18N
        buttonSplit.setText(resourceMap.getString("buttonSplit.text")); // NOI18N
        buttonSplit.setName("buttonSplit"); // NOI18N
        panelSplitControlButtons.add(buttonSplit);

        buttonSplitCancel.setAction(actionMap.get("onCancelSplit")); // NOI18N
        buttonSplitCancel.setText(resourceMap.getString("buttonSplitCancel.text")); // NOI18N
        buttonSplitCancel.setName("buttonSplitCancel"); // NOI18N
        panelSplitControlButtons.add(buttonSplitCancel);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
        mainSplitPanel.add(panelSplitControlButtons, gridBagConstraints);

        mainTabbedPane.addTab(resourceMap.getString("mainSplitPanel.TabConstraints.tabTitle"), mainSplitPanel); // NOI18N

        mainMergePanel.setName("mainMergePanel"); // NOI18N
        mainMergePanel.setLayout(new java.awt.GridBagLayout());

        panelMergeLeft.setName("panelMergeLeft"); // NOI18N
        panelMergeLeft.setLayout(new java.awt.GridLayout(1, 1, 0, 5));

        labelMergeFile.setText(resourceMap.getString("labelMergeFile.text")); // NOI18N
        labelMergeFile.setToolTipText(resourceMap.getString("labelMergeFile.toolTipText")); // NOI18N
        labelMergeFile.setAlignmentX(0.5F);
        labelMergeFile.setName("labelMergeFile"); // NOI18N
        panelMergeLeft.add(labelMergeFile);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(1, 5, 1, 3);
        mainMergePanel.add(panelMergeLeft, gridBagConstraints);

        panelMergeCenter.setName("panelMergeCenter"); // NOI18N
        panelMergeCenter.setLayout(new java.awt.GridLayout(1, 1, 0, 5));

        textFieldMergeFile.setText(resourceMap.getString("textFieldMergeFile.text")); // NOI18N
        textFieldMergeFile.setName("textFieldMergeFile"); // NOI18N
        panelMergeCenter.add(textFieldMergeFile);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.8;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 3);
        mainMergePanel.add(panelMergeCenter, gridBagConstraints);

        panelMergeRight.setName("panelMergeRight"); // NOI18N
        panelMergeRight.setLayout(new java.awt.GridLayout(1, 1, 0, 5));

        jButton1.setAction(actionMap.get("onBrowseMergeFile")); // NOI18N
        jButton1.setText(resourceMap.getString("jButton1.text")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N
        panelMergeRight.add(jButton1);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 1, 5);
        mainMergePanel.add(panelMergeRight, gridBagConstraints);

        panelMergeControlButtons.setName("panelMergeControlButtons"); // NOI18N

        buttonPerformMerge.setAction(actionMap.get("onPerformMerge")); // NOI18N
        buttonPerformMerge.setText(resourceMap.getString("buttonPerformMerge.text")); // NOI18N
        buttonPerformMerge.setName("buttonPerformMerge"); // NOI18N
        panelMergeControlButtons.add(buttonPerformMerge);

        buttonCancelMerge.setAction(actionMap.get("onCancelMerge")); // NOI18N
        buttonCancelMerge.setText(resourceMap.getString("buttonCancelMerge.text")); // NOI18N
        buttonCancelMerge.setName("buttonCancelMerge"); // NOI18N
        panelMergeControlButtons.add(buttonCancelMerge);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
        mainMergePanel.add(panelMergeControlButtons, gridBagConstraints);

        labelExplainMerge.setText(resourceMap.getString("labelExplainMerge.text")); // NOI18N
        labelExplainMerge.setName("labelExplainMerge"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(1, 5, 15, 5);
        mainMergePanel.add(labelExplainMerge, gridBagConstraints);

        mainTabbedPane.addTab(resourceMap.getString("mainMergePanel.TabConstraints.tabTitle"), mainMergePanel); // NOI18N

        mainPanel.add(mainTabbedPane);

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 280, Short.MAX_VALUE)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private Task splitTask;

    @Action
    public void onPerformSplit() {
        String selectedFile = textFieldSplitFile.getText();
        if (selectedFile == null || selectedFile.equals("") || !new File(selectedFile).exists()) {
            statusMessageLabel.setText("No such file exists!");
            return;
        }

        String selectedTargetDir = textFieldSplitTargetDir.getText();
        if (selectedTargetDir == null || selectedTargetDir.equals("") || !new File(selectedTargetDir).exists()) {
            statusMessageLabel.setText("No such directory exists!");
            return;
        }

        int limitMode = comboSplitParam.getSelectedIndex();
        String limitStr = textFieldSplitParam.getText();
        int limit = -1;
        try {
            limit = Integer.valueOf(limitStr);
        } catch (NumberFormatException nfe) {
            // ignore
        }

        if (limit <= 0) {
            if (limitMode == 0) {
                statusMessageLabel.setText("Wrong file size!");
            } else {
                statusMessageLabel.setText("Wrong number of files!");
            }
            return;
        }

        if (limitMode == 1) {
            long fileSize = -1;
            try {
                fileSize = new RandomAccessFile(selectedFile, "r").length();
            } catch (Exception e) {
                statusMessageLabel.setText("Cannot determine file size!");
            }
            int fileSizeKb = (int) Math.ceil(fileSize / 1024.0);
            limit = (int) Math.ceil(fileSizeKb / limit) + 1;
            System.out.println("File size: " + fileSize + " bytes, " + fileSizeKb + " Kb");
            System.out.println("Limit: " + limit + " Kb");
        }
        

        final String file = selectedFile;
        final String targetDir = selectedTargetDir;
        final int lim = limit;
        
        splitTask = new Task(getApplication()) {
            @Override
            protected Object doInBackground() throws Exception {
                fileUtil.splitFile(file, targetDir, lim, new FileWorkerListener() {

                    public void echoMessage(String msg) {
                        if (msg != null) {
                            doSetMessage(msg);
                        }
                    }
                });
                return null;
            }
            protected void doSetMessage(String msg) {
                setMessage(msg);
            }
        };
        getApplication().getContext().getTaskService().execute(splitTask);

    }

    private String currentFolder = System.getProperty("user.home");

    @Action
    public void onBrowseSplitFile() {
        JFileChooser fileChooser = new JFileChooser(currentFolder);
        int result = fileChooser.showOpenDialog(mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            currentFolder = selectedFile.getParent();
            textFieldSplitFile.setText(selectedFile.getAbsolutePath());
        }

    }

    private int inputSplitSize = 1440;
    private int inputSplitNumber = 2;

    @Action
    public void onSplitParamSelected() {
        int sel = comboSplitParam.getSelectedIndex();
        if (sel == 0) {
            // selected split size
            try {
                inputSplitNumber = Integer.valueOf(textFieldSplitParam.getText());
            } catch (NumberFormatException e) {
                // ignore
            }
            textFieldSplitParam.setText(inputSplitSize + "");
        } else {
            // selected number of files
            try {
            inputSplitSize = Integer.valueOf(textFieldSplitParam.getText());
            } catch (NumberFormatException e) {
                // ignore
            }
            textFieldSplitParam.setText(inputSplitNumber + "");
        }
    }

    @Action
    public void onCancelSplit() {
        if (splitTask != null && splitTask.isStarted()) {
            splitTask.cancel(false);
            fileUtil.clean();
        }
    }

    @Action
    public void onBrowseMergeFile() {
        if (currentTargetFolder == null) {
            currentTargetFolder = currentFolder;
        }
        JFileChooser fileChooser = new JFileChooser(currentTargetFolder);
        int result = fileChooser.showOpenDialog(mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            currentTargetFolder = selectedFile.getParent();
            textFieldMergeFile.setText(selectedFile.getAbsolutePath());
        }
    }

    private Task mergeTask;

    @Action
    public void onPerformMerge() {
        String mergeFile = textFieldMergeFile.getText();
        if (mergeFile == null || mergeFile.equals("") || !new File(mergeFile).exists()) {
            statusMessageLabel.setText("No such file exists!");
            return;
        }

        int i = mergeFile.lastIndexOf('.');
        String ext = mergeFile.substring(i + 1);
        try {
            Integer.valueOf(ext);
        } catch (NumberFormatException nfe) {
            statusMessageLabel.setText("Wrong merge file!");
            return;
        }
        mergeFile = mergeFile.substring(0, i);
        File file = new File(mergeFile);
        if (file.exists()) {
            statusMessageLabel.setText("Target file already exists!");
            return;
        }
        final String mergeFileFinal = mergeFile;

        mergeTask = new Task(getApplication()) {
            @Override
            protected Object doInBackground() throws Exception {
                setOkButtonsState(false);
                fileUtil.mergeFile(mergeFileFinal, new FileWorkerListener() {

                    public void echoMessage(String msg) {
                        if (msg != null) {
                            doSetMessage(msg);
                        }
                    }
                });
                setOkButtonsState(true);
                return null;
            }
            protected void doSetMessage(String msg) {
                setMessage(msg);
            }
        };
        getApplication().getContext().getTaskService().execute(mergeTask);
    }

    private void setOkButtonsState(boolean enable) {
        buttonPerformMerge.setEnabled(enable);
        buttonSplit.setEnabled(enable);
    }

    @Action
    public void onCancelMerge() {
        if (mergeTask != null && mergeTask.isStarted()) {
            mergeTask.cancel(false);
            fileUtil.clean();
        }
        setOkButtonsState(true);
    }

    private String currentTargetFolder = null;

    @Action
    public void onBrowseSplitTargetDir() {
        if (currentTargetFolder == null) {
            currentTargetFolder = currentFolder;
        }
        JFileChooser fileChooser = new JFileChooser(currentTargetFolder);
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int result = fileChooser.showOpenDialog(mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            currentTargetFolder = selectedFile.getAbsolutePath();
            textFieldSplitTargetDir.setText(currentTargetFolder);
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonBrowseSplitTargetDir;
    private javax.swing.JButton buttonCancelMerge;
    private javax.swing.JButton buttonPerformMerge;
    private javax.swing.JButton buttonSplit;
    private javax.swing.JButton buttonSplitCancel;
    private javax.swing.JButton buttonSplitFileBrowse;
    private javax.swing.JComboBox comboSplitParam;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel labelExplainMerge;
    private javax.swing.JLabel labelMergeFile;
    private javax.swing.JLabel labelSplitFile;
    private javax.swing.JLabel labelSplitParam;
    private javax.swing.JLabel labelSplitTargetDir;
    private javax.swing.JPanel mainMergePanel;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JPanel mainSplitPanel;
    private javax.swing.JTabbedPane mainTabbedPane;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JPanel panelMergeCenter;
    private javax.swing.JPanel panelMergeControlButtons;
    private javax.swing.JPanel panelMergeLeft;
    private javax.swing.JPanel panelMergeRight;
    private javax.swing.JPanel panelSplitControlButtons;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JPanel splitPanelCenter;
    private javax.swing.JPanel splitPanelLeft;
    private javax.swing.JPanel splitPanelRight;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JTextField textFieldMergeFile;
    private javax.swing.JTextField textFieldSplitFile;
    private javax.swing.JTextField textFieldSplitParam;
    private javax.swing.JTextField textFieldSplitTargetDir;
    // End of variables declaration//GEN-END:variables

    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;

    private JDialog aboutBox;
}
